/*
 * Copyright (C) 2011 Wojciech Dzierżanowski
 * See LICENSE.txt for licensing details.
 */

package wdzierzan.downstream.core;

/**
 * @author Wojciech Dzierzanowski (wojciech.dzierzanowski@gmail.com)
 */
public class GstPipelineBuilder {

    private final String hostname;
    private final int port;

    private GstPipelineBuilder(String hostname, int port) {
        this.hostname = hostname;
        this.port = port;
    }

    protected GstPipelineBuilder(GstPipelineBuilder other) {
        hostname = other.hostname;
        port = other.port;
    }

    public String from(String path) {
        return String.format(
                "filesrc location=%s %s! tcpclientsink host=%s port=%d sync=false",
                FileUtils.escape(path), getTranscoderFragment(), hostname, port);
    }

    protected String getTranscoderFragment() {
        return "";
    }

    public static class EncoderChoice extends GstPipelineBuilder {

        private EncoderChoice(GstPipelineBuilder other) {
            super(other);
        }

        public OggVorbisEncoder toOggVorbis() {
            return new OggVorbisEncoder(this);
        }

        public Mp3Encoder toMp3() {
            return new Mp3Encoder(this);
        }
    }

    public static class OggVorbisEncoder extends GstPipelineBuilder {

        private double quality = Double.NaN;

        private OggVorbisEncoder(GstPipelineBuilder other) {
            super(other);
        }

        public GstPipelineBuilder quality(double q) {
            if (!(-0.1 <= q && q <= 1.0)) {
                throw new IllegalArgumentException(
                        "quality " + quality + " is outside of [-0.1, 1]");
            }
            quality = q;
            return this;
        }

        @Override
        protected String getTranscoderFragment() {
            return String.format(
                    "! decodebin ! audioconvert ! vorbisenc %s! oggmux ",
                    !Double.isNaN(quality)
                            // Not using String.format() to prevent
                            // locale-dependent formatting.
                            ? "quality=" + Double.toString(quality) + ' '
                            : "");
        }
    }

    public static class Mp3Encoder extends GstPipelineBuilder {

        private int preset = Integer.MAX_VALUE;

        private Mp3Encoder(GstPipelineBuilder other) {
            super(other);
        }

        public GstPipelineBuilder preset(int p) {
            preset = p;
            return this;
        }

        @Override
        protected String getTranscoderFragment() {
            return String.format(
                    "! decodebin ! audioconvert ! lame %s! ffmux_mp3 ",
                    preset != Integer.MAX_VALUE
                            ? String.format("preset=%d ", preset)
                            : "");
        }
    }

    public static EncoderChoice via(String hostname, int port) {
        return new EncoderChoice(new GstPipelineBuilder(hostname, port));
    }
}
